using System;
using System.Collections.Generic;
using static SmartSite.Common.CheckingNullArgument;

namespace SmartSite.Frame
{
    public class DateTimeField : Field<DateTime>, IValueField<DateTime>
    {
        const int MaxCount = 32;

#pragma warning disable CA1822
        public DateTime MaxValue { get => GetDateTime(0x3F, 12, 31, 23, 59, 59); }
        public DateTime MinValue { get => GetDateTime(0, 1, 1, 0, 0, 0); }
#pragma warning restore

        IValueField<ulong> Year { get; }
        IValueField<ulong> Month { get; }
        IValueField<ulong> Day { get; }
        IValueField<ulong> Hour { get; }
        IValueField<ulong> Minute { get; }
        IValueField<ulong> Second { get; }

        public DateTimeField(List<byte> buffer, BitUnit index)
        : base(buffer, index, MaxCount)
        {
            Year = new ULongField(buffer, index, 6);
            Month = new ULongField(Year, 4);
            Day = new ULongField(Month, 5);
            Hour = new ULongField(Day, 5);
            Minute = new ULongField(Hour, 6);
            Second = new ULongField(Minute, 6);
        }

        public DateTimeField(IBytesBuffer buffer, BitUnit index)
        : this(CheckingNull(buffer, nameof(buffer)).Buffer, index) { }

        public DateTimeField(IField field)
        : this(CheckingNull(field, nameof(field)).Buffer, field.EndIndex) { }

        public override DateTime Value
        {
            get
            {
                return GetDateTime
                    (
                        (int)Year.Value,
                        (int)Month.Value,
                        (int)Day.Value,
                        (int)Hour.Value,
                        (int)Minute.Value,
                        (int)Second.Value
                    );
            }
            set
            {
                if (value < MinValue || value > MaxValue)
                    throw new ArgumentOutOfRangeException(nameof(value));

                Year.Value = (ulong)value.Year - 2010;
                Month.Value = (ulong)value.Month;
                Day.Value = (ulong)value.Day;
                Hour.Value = (ulong)value.Hour;
                Minute.Value = (ulong)value.Minute;
                Second.Value = (ulong)value.Second;
            }
        }


        static DateTime GetDateTime(int year, int month, int day, int hour, int minute, int second)
        {
            return new DateTime(year + 2010, month, day, hour, minute, second);
        }
    }
}